package com.ccp.dev.workflow.controller;

import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.RequestUtil;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.form.model.FormField;
import com.ccp.dev.form.service.FormFieldService;
import com.ccp.dev.form.util.FieldPool;
import com.ccp.dev.system.model.SysOrg;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysOrgService;
import com.ccp.dev.workflow.bpmconst.BpmConst;
import com.ccp.dev.workflow.model.BpmNodeUser;
import com.ccp.dev.workflow.model.bpm.PreViewModel;
import com.ccp.dev.workflow.service.ActDefModelService;
import com.ccp.dev.workflow.service.BpmNodeUserService;
import com.ccp.dev.workflow.service.BpmTaskExeService;
import com.ccp.dev.workflow.service.bpm.BpmNodeUserCalculationSelector;
import com.ccp.dev.workflow.service.bpm.IBpmNodeUserCalculation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * ClassDescribe:节点人员控制器类
 * @author :jiayueqiao
 * Date: 2019-07-11
 * Since:1
 */
@Controller
@RequestMapping(UrlConstants.PROJECT_ROOT +UrlConstants.PROJECT_MODULE_WORKFLOW+"/bpmNodeUser")
@Action(ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
public class BpmNodeUserController extends SysBaseController {
    private static final Logger logger = LoggerFactory.getLogger(BpmTaskExeService.class);

    @Resource
    private BpmNodeUserCalculationSelector bpmNodeUserCalculationSelector;
    @Resource
    private BpmNodeUserService bpmNodeUserService;
    @Resource
    private FormFieldService formFieldService;
    @Resource
    private ActDefModelService actDefModelService;
    @Resource
    private SysOrgService sysOrgService;

    /**
     * 预览数据信息计算
     * @param request
     * @return
     */
    @RequestMapping("/getByUserParams")
    @Action(description = "预览数据信息计算",detail = "预览数据信息计算")
    @ResponseBody
    public List<PreViewModel> getByUserParams(HttpServletRequest request){
        List<PreViewModel> list=new ArrayList<PreViewModel>();
        String params=RequestUtil.getString(request, "paramsJson");
        JSONArray jsonArray=JSONArray.fromObject(params);
        Set<PreViewModel> set =new HashSet<PreViewModel>();

        for(Object obj:jsonArray){
            JSONObject jsonObj=(JSONObject)obj;
            //cmpIds有可能问JSON对象，先获取字符串。
            String str= jsonObj.getString("cmpIds");
            jsonObj.remove("cmpIds");
            BpmNodeUser bpmNodeUser=(BpmNodeUser)JSONObject.toBean(jsonObj, BpmNodeUser.class);
            bpmNodeUser.setCmpIds(str);
            if(bpmNodeUser.getAssignType()==BpmNodeUser.ASSIGN_TYPE_SAME_NODE){
                continue;
            }

            Map<String,IBpmNodeUserCalculation> map= bpmNodeUserCalculationSelector.getBpmNodeUserCalculation();
            IBpmNodeUserCalculation calc=map.get(bpmNodeUser.getAssignType());
            if(calc.supportMockModel()){
                List<PreViewModel> preViewModelList= calc.getMockModel(bpmNodeUser);
                if(preViewModelList!=null&&!preViewModelList.isEmpty()){
                    set.addAll(preViewModelList);
                }
            }
        }
        if(set!=null&&!set.isEmpty()){
            list.addAll(set);
        }
        return list;
    }


    /**
     * 预览
     * @param request
     * @return
     */
    @RequestMapping("/preview")
    @Action(description = "人员设置预览查询",detail = "<#if success>人员设置预览查询数据成功</#if>")
    @ResponseBody
    public ResultData preview(HttpServletRequest request){
        //发起人id
        String startUserId=RequestUtil.getString(request, "startUserId");
        String preUserId=RequestUtil.getString(request, "preUserId");

        String formUserId=RequestUtil.getString(request, "formUserId");
        String formOrgId=RequestUtil.getString(request, "formOrgId");
        String formPosId=RequestUtil.getString(request, "formPosId");
        String formRoleId=RequestUtil.getString(request, "formRoleId");
        String startOrgId=RequestUtil.getString(request, "startOrgId");
        String startPosId=RequestUtil.getString(request, "startPosId");
        String startJobId=RequestUtil.getString(request, "startJobId");
        String preOrgId=RequestUtil.getString(request, "preOrgId");

        String nodeUser=request.getParameter("nodeUser");
        nodeUser = StringEscapeUtils.unescapeHtml4(nodeUser);
        if(StringUtil.isEmpty(nodeUser)){
            nodeUser = "";
        }
        JSONArray jsonArray=JSONArray.fromObject(nodeUser);

        List<BpmNodeUser> bpmNodeUsers = new ArrayList<BpmNodeUser>();
        //解析BpmNodeUser配置。
        for (int i = 0; i < jsonArray.size(); i++) {
            String userJson = jsonArray.getJSONObject(i).toString();
            JSONObject jsonObj= JSONObject.fromObject(userJson);
            String cmpIds=jsonObj.getString("cmpIds");
            jsonObj.remove("cmpIds");
            BpmNodeUser bpmNodeUser = (BpmNodeUser) JSONObject.toBean(jsonObj, BpmNodeUser.class);
            bpmNodeUser.setCmpIds(cmpIds);
            bpmNodeUsers.add(bpmNodeUser);
        }
        //构建表单流程变量。
        Map<String,Object> vars=new HashMap<String, Object>();

        if(StringUtil.isNotEmpty(formUserId)){
            vars.put(BpmConst.PREVIEW_FORMUSER, formUserId);
        }
        if(StringUtil.isNotEmpty(formOrgId)){
            vars.put(BpmConst.PREVIEW_FORMORG, formOrgId);
        }
        if(StringUtil.isNotEmpty(formPosId)){
            vars.put(BpmConst.PREVIEW_FORMPOS, formPosId);
        }
        if(StringUtil.isNotEmpty(formRoleId)){
            vars.put(BpmConst.PREVIEW_FORMROLE, formRoleId);
        }
        if(StringUtil.isNotEmpty(startOrgId)){
            vars.put(BpmConst.START_ORG_ID, startOrgId);
        }
        if(StringUtil.isNotEmpty(startPosId)){
            vars.put(BpmConst.START_POS_ID, startPosId);
        }
        if(StringUtil.isNotEmpty(startJobId)){
            vars.put(BpmConst.START_JOB_ID, startJobId);
        }

        if(StringUtil.isNotEmpty(preOrgId)){
            vars.put(BpmConst.PRE_ORG_ID, preOrgId);
        }
        List<SysUser> resultList=new ArrayList<SysUser>();
        for(BpmNodeUser bpmNodeUser:bpmNodeUsers){
            List<SysUser> userList =bpmNodeUserService.queryPreviewNodeUser(bpmNodeUser, startUserId, preUserId, null,  vars);
            if(BeanUtils.isEmpty(userList) ){
                continue;
            }
            resultList=userSetCal(bpmNodeUser.getCompType(),resultList,userList);
        }
        SysAuditThreadLocalHolder.putParamerter("success",true);
        return getResultDataSuccess("operation.success",resultList);
    }

    /**
     * 根据集合计算类型，进行集合运算
     * @param type
     * @param list1
     * @param list2
     * @return
     */
    private List<SysUser> userSetCal(Short type,List<SysUser> list1,List<SysUser> list2){
        if(list1.isEmpty()){
            return list2;
        }
        switch (type) {
            case BpmNodeUser.COMP_TYPE_AND:
                list1 = intersectSysUserList(list1,list2);
                break;
            case BpmNodeUser.COMP_TYPE_OR:
                list1 = unionSysUserList(list1,list2);
                break;
            case BpmNodeUser.COMP_TYPE_EXCLUDE:
                list1 = subtractSysUserList(list1,list2);
                break;
            default:
                break;
        }
        return list1;
    }

    /**
     * 交集运算
     * @param list1
     * @param list2
     * @return
     */
    private List<SysUser> intersectSysUserList(List<SysUser> list1,List<SysUser> list2){
        List<SysUser> users = new ArrayList<SysUser>();
        for(SysUser u:list1){
            if(list2.contains(u)){
                users.add(u);
            }
        }
        return users;
    }

    /**
     * 并集运算
     * @param list1
     * @param list2
     * @return
     */
    private List<SysUser> unionSysUserList(List<SysUser> list1,List<SysUser> list2){
        List<SysUser> users = new ArrayList<SysUser>();
        users.addAll(list1);
        for(SysUser u:list2){
            if(!users.contains(u)){
                users.add(u);
            }
        }

        return users;
    }

    /**
     * 差集运算
     * @param list1
     * @param list2
     * @return
     */
    private List<SysUser> subtractSysUserList(List<SysUser> list1,List<SysUser> list2){
        List<SysUser> users = new ArrayList<SysUser>();
        users.addAll(list1);
        for(SysUser u:list2){
            if(users.contains(u)){
                users.remove(u);
            }
        }
        return users;
    }

    /**
     * 人员设置 添加规则弹窗
     * @return 返回路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/addRule")
    @Action(description = "人员设置 添加规则弹窗",exectype = "页面跳转日志")
    public String windowAddRule(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        model.addAttribute("modelId",modelId);
        return getAutoView();
    }

    /**
     * 人员设置 添加脚本    弹窗
     * @return 返回路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/addScript")
    @Action(description = "人员设置 添加脚本弹窗",exectype = "页面跳转日志")
    public String windowAddScript(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        model.addAttribute("modelId",modelId);
        return getAutoView();
    }

    /**
     * 人员设置 人员脚本    弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/personScript")
    @Action(description = " 人员设置 人员脚本弹窗",exectype = "页面跳转日志")
    public String windowPersonScript(HttpServletRequest request, Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String windowName = RequestUtil.getString(request, "windowName");
        model.addAttribute("modelId", modelId)
                .addAttribute("nodeId", nodeId)
                .addAttribute("windowName", windowName);
        return getAutoView();
    }


    /**
     * 人员设置 条件脚本    弹窗
     * @return 返回路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/conditionScript")
    @Action(description = "人员设置 条件脚本弹窗",exectype = "页面跳转日志")
    public String windowConditionScript(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        model.addAttribute("modelId",modelId);
        return getAutoView();
    }
    /**
     * 人员设置 人员脚本选择    弹窗
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/choosePersonScript")
    @Action(description = "人员设置 人员脚本选择弹窗",exectype = "页面跳转日志")
    public String windowChoosePersonScript(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        model.addAttribute("modelId",modelId);
        return getAutoView();
    }

    /**
     * 人员设置 任务脚本选择    弹窗
     * @return 返回路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/chooseScript")
    @Action(description = " 人员设置 任务脚本选择弹窗",exectype = "页面跳转日志")
    public String windowChooseConditionScript(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        model.addAttribute("modelId",modelId);
        return getAutoView();

    }


    /**
     * 人员设置 与已执行节点相同执行人 弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userWindowNodeUser")
    @Action(description = "人员设置 与已执行节点相同执行人弹窗",exectype = "页面跳转日志")
    public String windowUserNodeUser(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request,"modelId");
        String nodeId = RequestUtil.getString(request,"nodeId");
        String windowName = RequestUtil.getString(request,"windowName");
        Map<String,String> userNodeMap = actDefModelService.getTaskNodes(modelId,nodeId);
        List<String> list = new ArrayList<String>(userNodeMap.values());
        model.addAttribute("modelId",modelId)
                .addAttribute("userNodeMap",userNodeMap)
                .addAttribute("mapList",list)
                .addAttribute("windowName",windowName)
                .addAttribute("nodeId",nodeId);
        return getAutoView();
    }
    /**
     * 人员设置 部门的上级类型部门的负责人 弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userWindowUpSection")
    @Action(description = "人员设置 部门的上级类型部门的负责人弹窗",exectype = "页面跳转日志")
    public String windowUpSectionUser(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String windowName = RequestUtil.getString(request, "windowName");
        List<SysOrg> sysOrgList = sysOrgService.queryAll();
        model.addAttribute("sysOrgList", sysOrgList)
            .addAttribute("windowName",windowName);
        return getAutoView();
    }

    /**
     * 人员设置 人员表单变量  弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userWindowFormVar")
    @Action(description = "人员设置 人员表单变量弹窗",exectype = "页面跳转日志")
    public String windowFormVarUser(HttpServletRequest request,Model model) {
        //获取参数
        String procDefId = RequestUtil.getString(request,"procDefId");
        String parentProcDefId = RequestUtil.getString(request,"parentProcDefId");
        //cmpIds封装隐藏文本框内容
        String cmpIds = RequestUtil.getString(request,"cmpIds");
        cmpIds = StringEscapeUtils.unescapeHtml4(cmpIds);
        //文本框内容容器
        int varType = 0;
        String varName = "";
        String userType= "";
        //判断文本框内容是否为空
        if(cmpIds!=null && cmpIds!=""){
            //文本框容器赋值
            JSONObject jsonObject = JSONObject.fromObject(cmpIds);
            varType =   jsonObject.getInt("type");
            varName =   jsonObject.getString("varName");
            //普通变量独有属性
            if( varType==6 ){
                userType    =   jsonObject.getString("userType");
            }
        }
        //获取FieldList，判断传参个数
        List<FormField> fieldList = formFieldService.queryFlowVarByFlowProcDefIdOrParentProcDefId(procDefId,parentProcDefId);
        //初始化List ，分别是用户、组织（组织负责人）、角色、岗位、普通变量
        List<FormField> userVarList = new ArrayList<FormField>();
        List<FormField> orgVarList  = new ArrayList<FormField>();
        List<FormField> roleVarList = new ArrayList<FormField>();
        List<FormField> posVarList  = new ArrayList<FormField>();
        List<FormField> otherList   = new ArrayList<FormField>();
        //填充List
        for(FormField field : fieldList){
            Short controlType = field.getControlType();
            if( controlType==null ) { continue;}
            switch(controlType){
                case FieldPool.SELECTOR_USER_SINGLE:
                    if(field.getIsHidden()!=1 ){    userVarList.add(field); }
                    break;
                case FieldPool.SELECTOR_USER_MULTI:
                    if(field.getIsHidden()!=1 ){    userVarList.add(field); }
                    break;
                case FieldPool.SELECTOR_ORG_SINGLE:
                    if(field.getIsHidden()!=1 ) {   orgVarList.add(field);  }
                    break;
                case FieldPool.SELECTOR_ORG_MULTI:
                    if(field.getIsHidden()!=1 ) {   orgVarList.add(field);  }
                    break;
                case FieldPool.SELECTOR_ROLE_SINGLE:
                    if(field.getIsHidden()!=1 ) {   roleVarList.add(field); }
                    break;
                case FieldPool.SELECTOR_ROLE_MULTI:
                    if(field.getIsHidden()!=1 ) {   roleVarList.add(field); }
                    break;
                case FieldPool.SELECTOR_POSITION_SINGLE:
                    if(field.getIsHidden()!=1 ) {   posVarList.add(field);  }
                    break;
                case FieldPool.SELECTOR_POSITION_MULTI:
                    if(field.getIsHidden()!=1 ) {   posVarList.add(field);  }
                    break;
                default:
                    if(field.getIsFlowVar()==1) {   otherList.add(field);   }
                    break;
            }
        }

        //封装Model
        model.addAttribute("userVarList",userVarList)
                .addAttribute("orgVarList",orgVarList)
                .addAttribute("roleVarList",roleVarList)
                .addAttribute("posVarList",posVarList)
                .addAttribute("otherList",otherList)
                .addAttribute("varType",varType)
                .addAttribute("varName",varName)
                .addAttribute("userType",userType);
        //跳转
        return getAutoView();
    }

    /**
     * 人员设置 发起人或上个任务执行人         弹窗
     * 人员设置 发起人或上个任务执行人的组织    弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userWindowStartOrUpNodeUser")
    @Action(description = "人员设置-发起人或上个任务执行人弹窗和发起人或上个任务执行人的组织弹窗",exectype = "页面跳转日志")
    public String windowStartOrUpNodeUser(HttpServletRequest request,Model model) {
        //判断是执行人的人员还是组织
        boolean isOrg  = RequestUtil.getBoolean(request,"isOrg",false);
        String cmpIds = RequestUtil.getString(request,"cmpIds");
        cmpIds = StringEscapeUtils.unescapeHtml4(cmpIds);
        String windowName = RequestUtil.getString(request,"windowName");
        String type="";
        String userType="";
        if(StringUtil.isNotEmpty(cmpIds)){
            JSONObject jsonObject=JSONObject.fromObject(cmpIds);
            type=jsonObject.getString("type");
            userType=jsonObject.getString("userType");
        }
        model.addAttribute("isOrg",isOrg)
                .addAttribute("type",type)
                .addAttribute("windowName",windowName)
                .addAttribute("userType",userType);
        return getAutoView();
    }

    /**
     * 人员设置 脚本弹窗
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userWindowScript")
    @Action(description = "人员设置 脚本弹窗",exectype = "页面跳转日志")
    public String windowUserScript(HttpServletRequest request,Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String windowName = RequestUtil.getString(request, "windowName");
        model.addAttribute("modelId", modelId)
                .addAttribute("nodeId", nodeId)
                .addAttribute("windowName", windowName);
        return getAutoView();
    }

    /**
     * 人员设置 添加脚本页面
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/script")
    @Action(description = "人员设置 添加脚本页面",exectype = "页面跳转日志")
    public String viewScript(HttpServletRequest request, Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        String data = RequestUtil.getString(request, "data");
        model.addAttribute("modelId", modelId);
        model.addAttribute("data", data);
        return getAutoView();
    }


    /**
     * 人员预览页面
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/preview")
    @Action(description = "人员预览页面",exectype = "页面跳转日志")
    public String viewPreview(HttpServletRequest request, Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        model.addAttribute("modelId", modelId);
        return getAutoView();
    }
    /**
     * 配置节点人员预览页面
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/userLook")
    @Action(description = "配置节点人员预览页面",exectype = "页面跳转日志")
    public String viewConfigurationUserLook(HttpServletRequest request, Model model) {
        String modelId = RequestUtil.getString(request, "modelId");
        String cksDataHidden = RequestUtil.getString(request, "cksDataHidden");
        String cksDataShow = RequestUtil.getString(request, "cksDataShow");
        String ces = RequestUtil.getString(request, "ces");
        model.addAttribute("modelId", modelId);
        model.addAttribute("cksDataHidden", cksDataHidden);
        model.addAttribute("cksDataShow", cksDataShow);
        model.addAttribute("ces", ces);
        return getAutoView();
    }
    /**
     * 配置抄送人员设置页面
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/otherParamCopier")
    @Action(description = "配置抄送人员设置页面",exectype = "页面跳转日志")
    public String windowOtherParamCopier(HttpServletRequest request,Model model){
        String modelId = RequestUtil.getString(request, "modelId");
        model.addAttribute("modelId", modelId);
        return getAutoView();
    }


}
